#include "threadpool.h"
#include<unistd.h>
#include<cstring>
#include<pthread.h>
#include<signal.h>
#define DEFAULT_MIN_THREADS 3
#define DEFAULT_MAX_THREADS 8
#define INCREASE_NUMS       2
#define DECREASE_NUMS       2
//将线程id清零
void exitThread(ThreadPool *pool,pthread_t tid)
{
    for (int i = 0; i < pool->m_maxThreadNums; i++)
    {
        if(pool->m_threads[i]==tid)
        {
            pool->m_threads[i] = 0;
            //线程退出
            pthread_exit(NULL);
        }
    }
}
void *workerThreadFunc(void *arg);
// 管理者线程函数
void *manageThreadFunc(void* arg)
{
    pthread_detach(pthread_self());
    ThreadPool *pool = (ThreadPool *)arg;
    while (true)
    {
        //休眠
        sleep(1);
        //加锁
        pthread_mutex_lock(&(pool->m_mutex));
        // 取出任务队列的任务个数
        //取出存活的线程数
        int queueSize = pool->m_queueSize;
        int aliveThreadNum = pool->m_aliveThreadNums;
        // 解锁
        pthread_mutex_unlock(&(pool->m_mutex));

        //取出忙碌的线程数
        pthread_mutex_lock(&(pool->m_busyMutex));
        int busyThreadNums = pool->m_busyThreadNums;
        pthread_mutex_unlock(&(pool->m_busyMutex));
        // printf("queueSize =%d,aliveThreadNums= %d ,busyThreadNums= %d\n", queueSize, aliveThreadNum, busyThreadNums);
        // 什么时候需要开辟新的线程
        // 任务队列任务数 大于 存活线程
        int addCnt = 0;
        int ret = 0;
        if ((queueSize > (aliveThreadNum - busyThreadNums)) && aliveThreadNum < pool->m_maxThreadNums)
        {
            pthread_mutex_lock(&(pool->m_mutex));
            for (int i = 0; i < pool->m_maxThreadNums && addCnt < INCREASE_NUMS; i++)
            {
                //探测
                if (pool->m_threads[i] == 0)
                {
                    ret=pthread_create(&(pool->m_threads[i]), NULL, workerThreadFunc, pool);
                    if (ret != 0)
                    {
                        perror("thread create error");
                        throw std::runtime_error("thread create error");
                    }
                    printf("%ld 加入线程池\n", pool->m_threads[i]);
                    addCnt++;
                    //活着的线程数++
                    (pool->m_aliveThreadNums)++;
                }
            }
            pthread_mutex_unlock(&(pool->m_mutex));
        }
    
        //什么时候需要减少线程池的线程数量
        //任务队列的任务数 远小于 存活（未工作）的任务数
        if (queueSize < (aliveThreadNum - busyThreadNums) && aliveThreadNum > pool->m_minThreadNums)
        {
            // 减少线程
            pthread_mutex_lock(&(pool->m_mutex));

            pool->m_exitNum += DECREASE_NUMS;
            for (int i = 0; i < DECREASE_NUMS;i++)
            {    
                pthread_cond_signal(&(pool->m_queueNotEmpty));
            }

            pthread_mutex_unlock(&(pool->m_mutex));
        }
    }
}
//工作者线程
void* workerThreadFunc(void* arg)
{
    //分离线程
    pthread_detach(pthread_self());
    ThreadPool *pool = (ThreadPool *)arg;
    //核心目的：去队列里取任务处理
    while(true)
    {
        pthread_mutex_lock(&(pool->m_mutex));
        while(pool->m_queueSize==0)
        {
            //休眠毫秒
            usleep(10000);
            pthread_cond_wait(&(pool->m_queueNotEmpty), &(pool->m_mutex));

            if(pool->m_exitNum>0)
            {
                if (pool->m_aliveThreadNums > pool->m_minThreadNums)
                {
                    (pool->m_exitNum)--;
                    //存活线程数减一
                    (pool->m_aliveThreadNums)--;
                    //解锁
                    pthread_mutex_unlock(&(pool->m_mutex));

                    printf("%ld 离开线程池\n", pthread_self());

                    //线程退出
                    exitThread(pool, pthread_self());
                }
            }
        }
        //从任务队列取数据
        Task_t newTask;
        newTask.function = pool->m_queue[pool->m_queueFront].function;
        newTask.arg = pool->m_queue[pool->m_queueFront].arg;
        // 移动队列队头
        pool->m_queueFront = (pool->m_queueFront + 1) % pool->m_queueCapacity;
        //任务队列任务数减一
        pool->m_queueSize--;
        pthread_mutex_unlock(&(pool->m_mutex));

        //锁2上锁
        pthread_mutex_lock(&(pool->m_busyMutex));
        //忙碌的线程数加一
        pool->m_busyThreadNums++;
        //锁2解锁
        pthread_mutex_unlock(&(pool->m_busyMutex));

        //处理任务
        newTask.function(newTask.arg);

        //锁2上锁
        pthread_mutex_lock(&(pool->m_busyMutex));
        //忙碌的线程数减一
        pool->m_busyThreadNums--;
        //锁2解锁
        pthread_mutex_unlock(&(pool->m_busyMutex));
        //发信号
        pthread_cond_signal(&(pool->m_queueNotFull));
    }
}
ThreadPool::ThreadPool(int minThreads, int maxThreads, int maxQueueCapacity)
{
    if(minThreads <= 0|| maxThreads <= 0)
    {
        minThreads = DEFAULT_MIN_THREADS;
        maxThreads = DEFAULT_MAX_THREADS;

    }
    this->m_minThreadNums = minThreads;
    this->m_maxThreadNums = maxThreads;
    this->m_queueCapacity = maxQueueCapacity;

    //任务队列数初始化
    this->m_queue = new Task_t[this->m_queueCapacity];
    if(this->m_queue==NULL)
    {
        perror("new error");
        _exit(-1);
    }
    //清空脏数据
    memset(this->m_queue, 0, sizeof(Task_t) * this->m_queueCapacity);

    //队列的属性
    this->m_queueSize = 0;
    this->m_queueFront = 0;
    this->m_queueTail = 0;

    //线程初始化
    this->m_threads = new pthread_t[this->m_maxThreadNums];
    if(this->m_threads==NULL)
    {
        perror("new error");
        _exit(-1);
    }
    //清空脏数据
    memset(this->m_threads, 0, sizeof(pthread_t) * this->m_maxThreadNums);

    //启动管理者线程
    int ret=pthread_create(&(this->manageThread), NULL, manageThreadFunc, this);
    if(ret==-1)
    {
        perror("thread create error");
        _exit(-1);
    }
    //忙碌的线程数
    this->m_busyThreadNums = 0;
    //存活的线程数
    this->m_aliveThreadNums = 0;
    for (int i = 0; i < m_minThreadNums; i++)
    {
        int ret=pthread_create(&(this->m_threads[i]), NULL, workerThreadFunc, this);
        if(ret==-1)
        {
            perror("thread create error");
            _exit(-1);
        }
        //存活的线程数加一
        this->m_aliveThreadNums++;
    }
    //锁的初始化
    pthread_mutex_init(&(this->m_mutex), NULL);
    //锁2的初始化
    pthread_mutex_init(&(this->m_busyMutex), NULL);
    //条件变量初始化
    pthread_cond_init(&(this->m_queueNotEmpty), NULL);
    pthread_cond_init(&(this->m_queueNotFull), NULL);
    //杀掉的线程数
    this->m_exitNum = 0;
}

ThreadPool::~ThreadPool() 
{
    //锁的销毁
    pthread_mutex_destroy(&(this->m_mutex));
    //锁2的销毁
    pthread_mutex_destroy(&(this->m_busyMutex));
    //条件变量销毁
    pthread_cond_destroy(&(this->m_queueNotEmpty));
}

void ThreadPool::addTask(void *(*funcion)(void *arg), void *arg)
{
    //将任务添加到任务队列
    //加锁
    pthread_mutex_lock(&(this->m_mutex));

    while(this->m_queueSize==this->m_queueCapacity)
    {
        pthread_cond_wait(&(this->m_queueNotFull), &(this->m_mutex));
    }

    this->m_queue[this->m_queueTail].function = funcion;
    this->m_queue[this->m_queueTail].arg = arg;

    this->m_queueTail = (this->m_queueTail + 1) % this->m_queueCapacity;
    // 任务数量加一
    this->m_queueSize++;

    //解锁
    pthread_mutex_unlock(&(this->m_mutex));
    //发信号
    pthread_cond_signal(&(this->m_queueNotEmpty));
}
